<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
	</head>
	<body>
		<script>function MyPromise(executor) {
  var self = this;
  self.status = 'pending';
  self.value = undefined;
  self.reason = undefined;
  self.onFulfilledCallbacks = []; // 存放成功回调函数
  self.onRejectedCallbacks = []; // 存放失败回调函数
  
  function resolve(value) {
    if (self.status === 'pending') {
      self.status = 'fulfilled';
      self.value = value;
      self.onFulfilledCallbacks.forEach(function(callback) {
        callback(value);
      });
    }
  }
  
  function reject(reason) {
    if (self.status === 'pending') {
      self.status = 'rejected';
      self.reason = reason;
      self.onRejectedCallbacks.forEach(function(callback) {
        callback(reason);
      });
    }
  }
  
  try {
    executor(resolve, reject);
  } catch(error) {
    reject(error);
  }
}

MyPromise.prototype.then = function(onFulfilled, onRejected) {
  var self = this;
  
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(value) {
    return value;
  }
  
  onRejected = typeof onRejected === 'function' ? onRejected : function(reason) {
    throw reason;
  }
  
  var promise2 = new MyPromise(function(resolve, reject) {
    if (self.status === 'fulfilled') {
      setTimeout(function() {
        try {
          var x = onFulfilled(self.value);
          resolvePromise(promise2, x, resolve, reject);
        } catch(error) {
          reject(error);
        }
      }, 0);
    }
    
    if (self.status === 'rejected') {
      setTimeout(function() {
        try {
          var x = onRejected(self.reason);
          resolvePromise(promise2, x, resolve, reject);
        } catch(error) {
          reject(error);
        }
      }, 0);
    }
    
    if (self.status === 'pending') {
      self.onFulfilledCallbacks.push(function() {
        setTimeout(function() {
          try {
            var x = onFulfilled(self.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch(error) {
            reject(error);
          }
        }, 0);
      });
      
      self.onRejectedCallbacks.push(function() {
        setTimeout(function() {
          try {
            var x = onRejected(self.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch(error) {
            reject(error);
          }
        }, 0)
      });
    }
  });
  
  return promise2;
}

function resolvePromise(promise, x, resolve, reject) {
  var then, thenCalled = false;
  if (promise === x) {
    reject(new TypeError('Chaining cycle detected for promise'));
  }
  
  if (typeof x === 'object' && x !== null || typeof x === 'function') {
    try {
      then = x.then;
      if (typeof then === 'function') {
        then.call(x, function(y) {
          if (thenCalled) return;
          thenCalled = true;
          resolvePromise(promise, y, resolve, reject);
        }, function(reason) {
          if (thenCalled) return;
          thenCalled = true;
          reject(reason);
        });
      } else {
        resolve(x);
      }
    } catch(error) {
      if (thenCalled) return;
      thenCalled = true;
      reject(error);
    }
  } else {
    resolve(x);
  }
}

MyPromise.prototype.catch = function(onRejected) {
  return this.then(null, onRejected);
}

MyPromise.resolve = function(value) {
  return new MyPromise(function(resolve, reject) {
    resolve(value);
  });
}

MyPromise.reject = function(reason) {
  return new MyPromise(function(resolve, reject) {
    reject(reason);
  });
}</script>
	</body>
</html>
